#include "videowidget.h"
#include <QOpenGLTexture>
#include <QDebug>
#include <libavcodec/avcodec.h>
#include <libavutil/imgutils.h>  // 确保你包含了这个头文件
#include <QOpenGLWidget>
#include <QOpenGLExtraFunctions>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLBuffer>
#include <QOpenGLShaderProgram>

extern "C"
{
    #include <libavcodec/avcodec.h>
    #include <libavformat/avformat.h>
    #include <libswscale/swscale.h>
    #include <libavdevice/avdevice.h>
    #include <libavformat/version.h>
    #include <libavutil/time.h>
    #include <libavutil/mathematics.h>
    #include <libavutil/imgutils.h>
}

VideoWidget::VideoWidget(const QString &streamUrl, QWidget *parent)
    : QOpenGLWidget(parent), pFrame(nullptr), pFrameRGB(nullptr), pCodecCtx(nullptr), pFormatCtx(nullptr), imgConvertCtx(nullptr), buffer(nullptr)
{
    initFFmpeg(streamUrl);

    // 设置定时器，用于更新视频帧
    timer = new QTimer(this);
    connect(timer, &QTimer::timeout, this, &VideoWidget::updateFrame);
    timer->start(1000 / 30);  // 假设 30 FPS 的帧率
}

VideoWidget::~VideoWidget()
{
    if (pFrame) av_frame_free(&pFrame);
    if (pFrameRGB) av_frame_free(&pFrameRGB);
    if (pCodecCtx) avcodec_free_context(&pCodecCtx);
    if (pFormatCtx) avformat_close_input(&pFormatCtx);
    if (imgConvertCtx) sws_freeContext(imgConvertCtx);
    delete[] buffer;
}

void VideoWidget::initFFmpeg(const QString &streamUrl)
{
    avformat_network_init();
    pFormatCtx = avformat_alloc_context();

    AVDictionary *opts = nullptr;

    // 使用 TCP 传输，减少丢包
    av_dict_set(&opts, "rtsp_transport", "tcp", 0);

    // 增加接收缓冲区大小，防止网络抖动导致丢包
    av_dict_set(&opts, "buffer_size", "1024000", 0);

    // 设置最大延迟，调整为网络条件合适的值
    av_dict_set(&opts, "max_delay", "100000", 0);  // 100ms 延迟

    // 启用低延迟模式，避免过多缓冲造成丢帧
    av_dict_set(&opts, "flags", "low_delay", 0);

    if (avformat_open_input(&pFormatCtx, streamUrl.toStdString().c_str(), nullptr, &opts) != 0) {
        qDebug() << "无法打开视频流";
        return;
    }

    if (avformat_find_stream_info(pFormatCtx, nullptr) < 0) {
        qDebug() << "无法获取视频流信息";
        return;
    }

    // 找到视频流
    for (unsigned int i = 0; i < pFormatCtx->nb_streams; i++) {
        if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
            videoStreamIndex = i;
            break;
        }
    }

    if (videoStreamIndex == -1) {
        qDebug() << "找不到视频流";
        return;
    }

    AVCodecParameters *codecParams = pFormatCtx->streams[videoStreamIndex]->codecpar;
    auto *pCodec = avcodec_find_decoder(codecParams->codec_id);
    if (!pCodec) {
        qDebug() << "解码器未找到";
        return;
    }

    pCodecCtx = avcodec_alloc_context3(pCodec);
    avcodec_parameters_to_context(pCodecCtx, codecParams);
    if (avcodec_open2(pCodecCtx, pCodec, nullptr) < 0) {
        qDebug() << "无法打开解码器";
        return;
    }

    // 分配帧和缓冲区
    pFrame = av_frame_alloc();
    pFrameRGB = av_frame_alloc();
    packet = av_packet_alloc();
    int numBytes = av_image_get_buffer_size(AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height, 1);
    buffer = (uint8_t *)av_malloc(numBytes * sizeof(uint8_t));

    av_image_fill_arrays(pFrameRGB->data, pFrameRGB->linesize, buffer, AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height, 1);
    imgConvertCtx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_RGB24, SWS_BICUBIC, nullptr, nullptr, nullptr);

    if (!imgConvertCtx) {
        qDebug() << "无法初始化图像转换上下文";
        return;
    }
}


void VideoWidget::initializeGL()
{
    initializeOpenGLFunctions();

    // 初始化 OpenGL 纹理
    glGenTextures(1, &textureID);
    glBindTexture(GL_TEXTURE_2D, textureID);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glBindTexture(GL_TEXTURE_2D, 0);
}

void VideoWidget::resizeGL(int w, int h)
{
    glViewport(0, 0, w, h);
}

void VideoWidget::paintGL()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    if (!pFrameRGB) return;

    // 绑定并更新 OpenGL 纹理
    glBindTexture(GL_TEXTURE_2D, textureID);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, pCodecCtx->width, pCodecCtx->height, 0, GL_RGB, GL_UNSIGNED_BYTE, pFrameRGB->data[0]);

    // 绘制视频帧，调整 y 轴翻转
    glEnable(GL_TEXTURE_2D);
    glBegin(GL_QUADS);
        glTexCoord2f(0.0f, 1.0f); glVertex2f(-1.0f, -1.0f);  // 左下角
        glTexCoord2f(1.0f, 1.0f); glVertex2f( 1.0f, -1.0f);  // 右下角
        glTexCoord2f(1.0f, 0.0f); glVertex2f( 1.0f,  1.0f);  // 右上角
        glTexCoord2f(0.0f, 0.0f); glVertex2f(-1.0f,  1.0f);  // 左上角
    glEnd();
    glDisable(GL_TEXTURE_2D);

    // 解绑纹理
    glBindTexture(GL_TEXTURE_2D, 0);
}

void VideoWidget::updateFrame()
{
    decodeFrame();
    update();  // 刷新界面
}

void VideoWidget::decodeFrame()
{
    AVPacket packet;
    while (av_read_frame(pFormatCtx, &packet) >= 0) {
        if (packet.stream_index == videoStreamIndex) {
            if (avcodec_send_packet(pCodecCtx, &packet) == 0) {
                if (avcodec_receive_frame(pCodecCtx, pFrame) == 0) {
                    // 转换为 RGB
                    sws_scale(imgConvertCtx, (uint8_t const * const *)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
                    av_packet_unref(&packet);
                    break;
                }
            }
        }
        av_packet_unref(&packet);
    }
}
